package com.theexceptions.todo.model;

import java.util.Calendar;
import java.util.List;

public interface IPersister {
	
	/**
	 * Prepares the storage system for use for the first time.
	 * Does nothing if the storage system is ready.
	 */
	public void init();

	/**
	 * @param userID The userID of the user to whom the new category belongs.
	 * @param categoryName The name the new category.
	 * @return True if insertion was successful; false if a category with
	 *         categoryName for the user with userID already exists.
	 */
	public boolean insertCategory(long userID, String categoryName);
	
	/**
	 * Inserts a Location into the database.
	 * @param name The name of the location to be added.
	 * @param userId The id of the user to whom the location belongs.
	 * @param longitude The longitude of the location to be added.
	 * @param latitude The latitude of the location to be added.
	 * @return The id of the location that was added.
	 */
	public long insertLocation(String name, long userId, long longitude, long latitude);
	
	/**
	 * Inserts a new task into the database.
	 * 
	 * @pre If time != null, the time has been set.
	 * @param time The date that the task is due, or null if task has no due date.
	 * @param locationId The id of the location where the task is or null if no location
	 * @param repeatId The id of how often this task repeats, or null if the task does not repeat.
	 * @param category The category of the task to add. May be null.
	 * @param description A description of the task, or null if no description
	 * @return The row ID of the newly inserted task, or -1 if an error occurred
	 */
	public long insertTask(long userID, String name, Calendar time, Long locationId, Long repeatId, String category, String description);
	
	/**
	 * Inserts a new user into the database.
	 * 
	 * @param username New User's username
	 * @param password New User's password
	 * @param name New User's name
	 * @param email New User's email
	 * @return The row ID of the newly inserted user, or -1 if one of the values
	 *         is not within the constraints of the database
	 */
	public long insertUser(String username, String password, String name, String email);
	
	/**
	 * Modifies a user with the specified ID.
	 * 
	 * @param userID ID of user to modify
	 * @param username User's new username
	 * @param password User's new password
	 * @param name User's new name
	 * @param email User's new email
	 * @return A new user object with the changed information, null if
	 *         modification unsuccessful.
	 */
	public User modifyUser(long userID, String username, String password, String name, String email);
	
	/**
	 * Removes a location from storage.
	 * @param locId The id of the location to be removed.
	 */
	public void removeLocation(long locId);
	
	/**
	 * @param userID The user's id of the categories to retrieve.
	 * @return A List of the category names.
	 */
	public List<String> retrieveCategories(long userID);
	
	/**
	 * Returns a list of the user's current task locations.
	 * 
	 * @param userID
	 * @return list of locations
	 */
	public List<Location> retrieveLocations(long userID);
	
	/**
	 * @param userID The User's id of the tasks to be retrieved from the
	 *            database.
	 * @return A list of tasks of the User with userID
	 */
	public List<Task> retrieveTasks(long userID);
	
	/**
	 * @param userID The id of the user whose tasks to retrieve.
	 * @param category The name of the category of the tasks to retrieve
	 * @return The tasks with that category.
	 */
	public List<Task> retrieveTasksByCategory (long userID, String category);
	
	/**
	 * @param userID The id of the user whose tasks to retrieve.
	 * @param isCompleted If true, returns the methods that are completed; if false, returns the tasks that are not completed
	 * @return The tasks filter by their completion
	 */
	public List<Task> retrieveTasksByCompletion(long userID, boolean isCompleted);
	
	/**
	 * @param userID The id of the user whose tasks to retrieve.
	 * @param date The date after which the Tasks should be retrieved
	 * @return The tasks due after date.
	 */
	public List<Task> retrieveTasksByDate(long userID, Calendar date);
	
	/**
	 * Retrieves a user's tasks with applied filters.
	 * @param filters
	 * @return Filtered list of tasks
	 */
	public List<Task> retrieveTasksWithFilters(long userID, List<TaskFilter> filters);
	
	/**
	 * Retrieves a user from the database.
	 * 
	 * @param userID User's ID
	 * @return The user's information contained in an object, or EMPTY_USER if
	 *         an error occurred
	 */
	public User retrieveUser(long userID);
	
	/**
	 * @param username
	 * @return The user with username or EMPTY_USER if no user with username
	 *         exists.
	 */
	public User retrieveUser(String username);
	
	/**
	 * Toggles whether a task has been completed or not
	 * 
	 * @param task
	 * @return Task's new "completed" state.
	 */
	public boolean toggleTaskCompleted(Task task);
	
	/**
	 * Removes all data from the tables and adds default data.
	 */
	public void clearTables();
}
